import com.powerfl.frm.taf.*;

import flash.events.*;
import flash.ui.*;
import flash.utils.*;

private var _keydown:Vector.<int>;
private var _keydowned:Vector.<int>;
private var _keydownEach:Vector.<Vector.<String>>;
private var _keyup:Vector.<int>;
private var _keyLastUp:int;
private var _keyFlow:Dictionary;
private var _keyEntered:int;

private function keyInit():void{
	_keydown = new Vector.<int>( 230, true );
	_keydowned = new Vector.<int>( 230, true );
	_keydownEach = new Vector.<Vector.<String>>( 230, true );
	_keyup = new Vector.<int>( 230, true );
	_keyFlow = new Dictionary( true );
}
//----------------------------------------------------------------------------------------------------------------------
final public function keyDownByName( $keyName:String ):int{
	return keyDown( keyCode( $keyName ) );
}
final public function keyUpByName( $keyName:String ):int{
	return keyUp( keyCode( $keyName ) );
}
final public function keyDownedByName( $keyName:String ):int{
	return keyDowned( keyCode( $keyName ) );
}
final public function keyDown( $keyCode:int ):int{
	return SELF._keydown[$keyCode];
}
final public function keyUp( $keyCode:int ):int{
	if( SELF._keyup[$keyCode] < 0 ){
		SELF._keyup[$keyCode] = 0;
		return -1;
	}else{
		return 0;
	}
}
final public function keyDowned( $keyCode:uint ):int{
	if( SELF._keydowned[$keyCode] < 0 ){
		SELF._keydowned[$keyCode] = 0;
		return -1;
	}else{
		return 0;
	}
}
//----------------------------------------------------------------------------------------------------------------------
private function keyCode( $keyName:* ):int{
	if( $keyName is String ){
		$keyName = $keyName.toUpperCase();
		if( $keyName in Keyboard ){
			return Keyboard[$keyName];
		}else if( $keyName in KEYCODE ){
			return KEYCODE[$keyName];
		}else{
			error( '알 수 없는 키 이름입니다 - ' + $keyName );
			return 0;
		}
	}else{
		return $keyName;
	}
}
private function keyAddFlow( $key:*, $flow:* ):void{
	var key:*, flow:Function, runner:Function, arg:Array;
	if( SELF._keyFlow[$flow] ){}else{
		if( $flow is String ){
			key = $flow;
			flow = flowGet( $flow );
		}else if( $flow is Array ){
			key = $flow[0];
			flow = flowGet( $flow[0] );
			arg = $flow.slice( 1 );
		}else if( $flow is Function ){
			key = $flow;
			flow = $flow;
		}else{
			error( '알 수 없는 flow인자입니다.' );
		}
		if( $key is String ){
			$key = keyCode( $key );
		}
		runner = function( ...$param ):void{
			if( SELF._keydown[$key] < 0 ){
				flow.apply( null, arg );
			}
		}
		SELF._keyFlow[key] = runner;
		++SELF._keyEntered;
	}
	if( SELF._keyEntered === 1 ){
		bindRunner( ['@@KEY_ENTER'], SELF._fixedLogic );
	}
}
private function keyRemoveFlow( $flow:* ):void{
	var idx:int;
	if( SELF._keyFlow[$flow] ){
		SELF._keyFlow[$flow] = null;
		delete SELF._keyFlow[$flow];
		--SELF._keyEntered;
		if( SELF._keyEntered === 0 ){
			unbindRunner( ['@@KEY_ENTER'], SELF._fixedLogic );
		}
	}
}
private function keyAddEachKey( $keyCode:uint, $flow:String ):void{
	var temp:Vector.<String>;
	if( SELF._keydownEach[$keyCode] === null ){
		SELF._keydownEach[$keyCode] = new Vector.<String>();
	}
	temp = SELF._keydownEach[$keyCode];
	if( temp.indexOf( $flow ) === -1 ){ 
		temp[temp.length] = $flow;
	}
}
private function keyRemoveEachKey( $keyCode:uint, $flow:String ):void{
	var temp:Vector.<String>, idx:int;
	if( SELF._keydownEach[$keyCode] === null ){
	}else if( $flow === '' ){
		SELF._keydownEach[$keyCode].length = 0;
	}else{
		temp = SELF._keydownEach[$keyCode];
		idx = temp.indexOf( $flow );
		if( idx > -1 ){ 
			temp.splice( idx, 1 );
		}
	}
}
//----------------------------------------------------------------------------------------------------------------------
private function KEY_ENTER():void{
	var key:*;
	for each( key in _keyFlow ){
		key(); 
	}
}
private function KEY_DOWN( $e:KeyboardEvent ):void{
	var code:int, key:*;
	code = $e.keyCode;
	if( SELF._keydown[code] === 0 ){
		SELF._keydowned[code] = SELF._keydown[code] = -1;
		if( _keydownEach[code] ){
			for each( key in SELF._keydownEach[code] ){
				flowCall( key );
			}
		}
	} 
}
private function KEY_UP( $e:KeyboardEvent ):void{
	var code:int;
	code = $e.keyCode;
	SELF._keyup[_keyLastUp] = SELF._keydowned[code] = SELF._keydown[code] = 0;
	SELF._keyup[code] = -1;
	SELF._keyLastUp = code;
}